/*
 * WriterItemDestination.java
 *
 * Created on September 28, 2003, 8:18 PM
 */

package org.infoset.xml.util;

import java.io.*;
import java.util.*;
import org.infoset.xml.*;

/**
 *
 * @author  alex
 */
public class WriterItemDestination implements ItemDestination,Serialization {
   
   static Name xmlMethod = InfosetFactory.getDefaultInfoset().createName("xml");
   static Name htmlMethod = InfosetFactory.getDefaultInfoset().createName("html");
   static Name xhtmlMethod = InfosetFactory.getDefaultInfoset().createName("xhtml");
   static Name textMethod = InfosetFactory.getDefaultInfoset().createName("text");

   String doctypeSystemId;
   String doctypePublicId;
   List cdataElements;
   OutputStream os;
   Writer out;
   String encoding;
   Name method;
   boolean closeOnEnd;
   XMLWriter xmlWriter;
   boolean textOnly;
   boolean textSet;
   boolean preferDefault;
   boolean useCharacterReferences;
   boolean omitXMLDecl;
   
   public WriterItemDestination(OutputStream os) {
      this(os,false);
   }
   
   public WriterItemDestination(OutputStream os,boolean closeOnEnd) {
      this.os = os;
      this.out = null;
      this.encoding = null;
      this.closeOnEnd = closeOnEnd;
      this.xmlWriter = null;
      this.cdataElements = new ArrayList();
      this.method = xmlMethod;
      this.preferDefault = false;
      this.textSet = false;
      this.textOnly = false;
      this.useCharacterReferences = false;
      this.omitXMLDecl = false;
      this.doctypeSystemId = null;
      this.doctypePublicId = null;
   }
   /** Creates a new instance of WriterItemDestination */
   public WriterItemDestination(Writer out,String encoding) {
      this(out,encoding,false);
   }
   
   public WriterItemDestination(Writer out,String encoding,boolean closeOnEnd) {
      this.out = out;
      this.encoding = encoding;
      this.closeOnEnd = closeOnEnd;
      this.xmlWriter = null;
      this.cdataElements = new ArrayList();
      this.method = xmlMethod;
      this.preferDefault = false;
      this.textSet = false;
      this.textOnly = false;
      this.useCharacterReferences = false;
      this.omitXMLDecl = false;
   }
   
   public void setUseCharacterReferences(boolean flag) {
      useCharacterReferences = flag;
   }
   
   public void send(Item item) 
      throws XMLException
   {
      if (out==null) {
         try {
            if (encoding==null) {
               out = new OutputStreamWriter(os,"UTF-8");
            } else {
               out = new OutputStreamWriter(os,encoding);
            }
         } catch (UnsupportedEncodingException ex) {
            throw new XMLException("Encoding is not supported.",ex);
         }
      }
      if (!textSet && xmlWriter==null) {
         if (method!=null && method.equals(textMethod)) {
            textOnly = true;
            textSet = true;
         } else {
            xmlWriter = new XMLWriter(true,new WriterSerializer(out,encoding,closeOnEnd));
            xmlWriter.setPreferDefault(preferDefault);
            xmlWriter.setUseCharacterReferences(useCharacterReferences);
            xmlWriter.setOmitXMLDeclaration(getOmitXMLDeclaration());
         }
      }

      if (textOnly) {
         switch (item.getType()) {
            case CharactersItem:
               try {
                  out.write(((Characters)item).getText());
               } catch (IOException ex) {
                  throw new XMLException("I/O error while writing XML.",ex);
               }
               break;
            case DocumentEndItem:
               try {
                  out.flush();
               } catch (IOException ex) {
                  throw new XMLException("I/O error while writing XML.",ex);
               }
         }
      } else {
         xmlWriter.write(item);
      }
   }

   public boolean getByteOrderMark()
   {
      return false;
   }

   public java.util.List getCDataElements()
   {
      return cdataElements;
   }

   public java.util.Map getCharaterMap()
   {
      return null;
   }

   public String getDoctypePublicId()
   {
      return doctypePublicId;
   }

   public String getDoctypeSystemId()
   {
      return doctypeSystemId;
   }

   public String getEncoding()
   {
      return encoding;
   }

   public boolean getEscapeURIAttributes()
   {
      return false;
   }

   public boolean getIndent()
   {
      return false;
   }

   public String getMediaType()
   {
      return null;
   }

   public Name getMethod()
   {
      return method;
   }

   public String getNormalizationForm()
   {
      return null;
   }

   public boolean getOmitXMLDeclaration()
   {
      return omitXMLDecl;
   }

   public String getStandalone()
   {
      return null;
   }

   public boolean getUndeclarePrefixes()
   {
      return false;
   }

   public String getVersion()
   {
      return null;
   }
   
   public boolean getPreferDefault() {
      return preferDefault;
   }

   public void setByteOrderMark(boolean value)
   {
   }

   public void setCharacterMap(java.util.Map value)
   {
   }

   public void setDoctypePublicId(String value)
   {
      doctypePublicId = value;
   }

   public void setDoctypeSystemId(String value)
   {
      doctypeSystemId = value;
   }

   public void setEncoding(String value)
   {
      encoding = value;
   }

   public void setEscapeURIAttributes(boolean value)
   {
   }

   public void setIndent(boolean value)
   {
   }

   public void setMediaType(String value)
   {
   }

   public void setMethod(Name outputMethod)
   {
      method = outputMethod;
   }

   public void setNormalizationForm(String value)
   {
   }

   public void setOmitXMLDeclaration(boolean value)
   {
      omitXMLDecl = value;
   }

   public void setStandalone(String value)
   {
   }

   public void setUndeclarePrefixes(boolean value)
   {
   }

   public void setVersion(String value)
   {
   }
   
   public void setPreferDefault(boolean value) {
      this.preferDefault = value;
   }

   public void end() throws XMLException
   {
   }

   public void start() throws XMLException
   {
   }
   
}
